import { BullModule } from '@nestjs/bullmq';
import {
  ClassSerializerInterceptor,
  MiddlewareConsumer,
  Module,
} from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { APP_GUARD, APP_INTERCEPTOR } from '@nestjs/core';
import { JwtModule } from '@nestjs/jwt';
import { ServeStaticModule } from '@nestjs/serve-static';
import { ThrottlerModule } from '@nestjs/throttler';
import { TypeOrmModule } from '@nestjs/typeorm';
import { HeaderResolver, I18nJsonLoader, I18nModule } from 'nestjs-i18n';
import { join } from 'path';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ApiResponseInterceptor } from './common/interceptors/api-response.interceptor';
import { LoggerMiddleware } from './common/middlewares/logger.middleware';
import { DemoModule } from './module/demo/demo.module';
import { EmailModule } from './module/shared/email/email.module';
import { MinioModule } from './module/shared/minio/minio.module';
import { RedisModule } from './module/shared/redis/redis.module';
import { AdminModule } from './module/sys/admin/admin.module';
import { AuthGuard } from './module/sys/auth/auth.guard';
import { AuthModule } from './module/sys/auth/auth.module';
import { DictModule } from './module/sys/dict/dict.module';
import { MenuModule } from './module/sys/menu/menu.module';
import { PermissionModule } from './module/sys/permission/permission.module';
import { RoleModule } from './module/sys/role/role.module';
import { UserModule } from './module/user/user.module';

const envFilePath = ['.env'];
export const IS_DEV = process.env.RUNNING_ENV !== 'prod';

if (IS_DEV) {
  envFilePath.unshift('.env.dev');
} else {
  envFilePath.unshift('.env.prod');
}

@Module({
  imports: [
    // 管理后台
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', '..', 'x-opentrons-manager/dist'),
      serveRoot: '/manager',
      exclude: ['/api/(.*)'],
    }),
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: envFilePath,
    }),
    ThrottlerModule.forRoot([
      {
        limit: 3,
        ttl: 10000,
      },
    ]),
    I18nModule.forRoot({
      fallbackLanguage: 'zh',
      loader: I18nJsonLoader,
      loaderOptions: {
        path: join(__dirname, '/i18n/'),
        watch: true,
      },
      resolvers: [{ use: HeaderResolver, options: ['language'] }],
    }),
    BullModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        connection: {
          host: configService.get('REDIS_HOST', '127.0.0.1'),
          port: configService.get('REDIS_PORT', 6379),
          db: configService.get('BULL_MQ_DB', 0),
        },
      }),
      inject: [ConfigService],
    }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        return {
          type: 'mysql',
          host: configService.get('DB_HOST'),
          port: configService.get('DB_PORT'),
          username: configService.get('DB_USERNAME'),
          password: configService.get('DB_PASSWORD'),
          database: configService.get('DB_DATABASE'),
          synchronize: configService.get('DB_SYNC') === 'true',
          timezone: configService.get('DB_TIMEZONE'),
          logging: configService.get('DB_LOGGING') === 'true',
          // 每个通过forFeature()注册的实体都会自动添加到配置对象的entities数组
          autoLoadEntities: true,
          cache: {
            type: 'ioredis',
            ignoreErrors: true,
            options: {
              host: configService.get<string>('REDIS_HOST', '127.0.0.1'),
              port: configService.get<number>('REDIS_PORT', 6379),
              db: 1,
            },
          },
        };
      },
    }),
    JwtModule.registerAsync({
      global: true,
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) => {
        return {
          secret: configService.get<string>('JWT_SECRET'),
          signOptions: {
            expiresIn: configService.get<string>('JWT_EXPIRES_IN'),
          },
        };
      },
    }),
    UserModule,
    RoleModule,
    PermissionModule,
    AdminModule,
    MenuModule,
    DemoModule,
    AuthModule,
    RedisModule,
    EmailModule,
    DictModule,
    MinioModule,
  ],
  controllers: [AppController],
  providers: [
    AppService,
    {
      provide: APP_INTERCEPTOR,
      useClass: ApiResponseInterceptor,
    },
    {
      provide: APP_INTERCEPTOR,
      useClass: ClassSerializerInterceptor,
    },
    {
      provide: APP_GUARD,
      useClass: AuthGuard,
    },
  ],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes('*');
  }
}
